package cn.iocoder.yudao.module.member.service.siteconfiguration;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.MemberDeviceConfigVo;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.SiteConfigurationVo;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.SysLinkVo;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.UserPoolConfigVo;
import cn.iocoder.yudao.module.member.convert.siteconfiguration.SiteConfigurationConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.siteconfiguration.SiteConfigurationDO;
import cn.iocoder.yudao.module.member.dal.mysql.siteconfiguration.SiteConfigurationMapper;
import cn.iocoder.yudao.module.member.dal.redis.no.OrderNoRedisDAO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.LINK_FLAG_TRUE;

@Service
@Validated
@Slf4j
public class SiteConfigurationServiceImpl implements SiteConfigurationService {


    @Resource
    private SiteConfigurationMapper siteConfigurationMapper;
    @Resource
    private UserPoolConfigService userPoolConfigService;
    @Resource
    private MemBerDeviceConfigService memBerDeviceConfigService;
    @Resource
    private OrderNoRedisDAO orderNoRedisDAO;
    @Resource
    private SysLinkService sysLinkService;

    @Resource(name = "signTaskExecutor")
    @Lazy
    private ThreadPoolTaskExecutor signTaskExecutor;

    private final String SITE_CONFIG = "site:config";
    //前端站点配置的微信缓存信息
    private final String SITE_CONFIG_CACHE_WECHATROBOT = "SITE:CONFIG:CACHE:WECHATROBOT";
    private final String SITE_CONFIG_CACHE_TOKEN = "SITE:CONFIG:CACHE:TOKEN";
    private final String SITE_CONFIG_CACHE_AUTOMATIC_FLAG = "SITE:CONFIG:CACHE:AUTOMATIC:FLAG";

    private final String SITE_CONFIG_CACHE_MAIN_URL = "SITE:CONFIG:CACHE:MAIN:URL";
    private final String SITE_CONFIG_CACHE_MAIN_CODE = "SITE:CONFIG:CACHE:MAIN:CODE";

    /**
     * 保存前端站点配置信息
     * 当前配置具有唯一属性
     *
     * @param saveReqVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveConfig(SiteConfigurationVo saveReqVO) {
        Long aLong = siteConfigurationMapper.selectCount();
        if (aLong > 0) {
            throw new RuntimeException("当前站点已存在配置,请修改");
        }
        //手动设置编码
        String generate = orderNoRedisDAO.generate(SITE_CONFIG);
        SiteConfigurationDO convert = SiteConfigurationConvert.INSTANCE.convert(saveReqVO);
        convert.setSiteCode(generate);
        convert.setId(null);
        if (StrUtil.isNotEmpty(saveReqVO.getWeChatRobot())) {
            orderNoRedisDAO.refreshCatch(SITE_CONFIG_CACHE_WECHATROBOT, saveReqVO.getWeChatRobot());
        }

        if (CollectionUtil.isNotEmpty(saveReqVO.getSysLinkVos())) {
            List<SysLinkVo> trueFlagLink = saveReqVO.getSysLinkVos().stream().filter(t -> t.getAutomaticFlag().equals(Boolean.TRUE)).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(trueFlagLink)) {
                if (trueFlagLink.size() > 1) {
                    throw exception(LINK_FLAG_TRUE);
                }
                //保存
                SysLinkVo sysLinkVo = trueFlagLink.get(0);
                if (StrUtil.isNotEmpty(sysLinkVo.getMainUrl())) {
                    orderNoRedisDAO.refreshCatch(SITE_CONFIG_CACHE_MAIN_URL, sysLinkVo.getMainUrl());
                }
                if (StrUtil.isNotEmpty(sysLinkVo.getMainCode())) {
                    orderNoRedisDAO.refreshCatch(SITE_CONFIG_CACHE_MAIN_CODE, sysLinkVo.getMainCode());
                }
                if (ObjectUtil.isNotEmpty(sysLinkVo.getAutomaticFlag())) {
                    orderNoRedisDAO.refreshCatch(SITE_CONFIG_CACHE_AUTOMATIC_FLAG, sysLinkVo.getAutomaticFlag().toString());
                } else {
                    orderNoRedisDAO.refreshCatch(SITE_CONFIG_CACHE_AUTOMATIC_FLAG, Boolean.FALSE.toString());
                }
                if (StrUtil.isNotEmpty(sysLinkVo.getToken())) {
                    orderNoRedisDAO.refreshCatch(SITE_CONFIG_CACHE_TOKEN, sysLinkVo.getToken());
                }
            } else {
                orderNoRedisDAO.refreshCatch(SITE_CONFIG_CACHE_AUTOMATIC_FLAG, Boolean.FALSE.toString());
            }
            saveReqVO.getSysLinkVos().forEach(t -> t.setSiteCode(generate));
        } else {
            orderNoRedisDAO.refreshCatch(SITE_CONFIG_CACHE_AUTOMATIC_FLAG, Boolean.FALSE.toString());
        }


        siteConfigurationMapper.insert(convert);
        saveReqVO.getMemberDeviceConfigVos().forEach(t -> t.setSiteCode(generate));
        saveReqVO.getUserPoolConfigs().forEach(t -> t.setSiteCode(generate));
        userPoolConfigService.saveConfig(saveReqVO);
        memBerDeviceConfigService.saveConfig(saveReqVO);
        sysLinkService.saveConfig(saveReqVO);
        this.refreshSignExecutorCoreSize(convert.getNumberLimit());

    }


    private void refreshSignExecutorCoreSize(Integer coreSize) {
        if(null==coreSize){
            log.info("核心线程数为空，不进行调整");
            return;
        }
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCompletion(int status) {
                if (status == TransactionSynchronization.STATUS_COMMITTED) {
                    log.info("调整配置 修改签名任务核心线程数,{}", coreSize);
                    signTaskExecutor.setCorePoolSize(coreSize);
                }
            }
        });

    }

    /**
     * 获取前端站点配置详细信息
     *
     * @return
     */
    @Override
    public SiteConfigurationVo getConfig() {
        List<SiteConfigurationDO> list = siteConfigurationMapper.selectList();
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        SiteConfigurationVo result = SiteConfigurationConvert.INSTANCE.convert(list.get(0));
        List<UserPoolConfigVo> userPoolConfigVos = userPoolConfigService.getConfig();
        List<MemberDeviceConfigVo> memberDeviceConfigVos = memBerDeviceConfigService.getConfig();
        List<SysLinkVo> sysLinkVos = sysLinkService.getConfig();
        result.setMemberDeviceConfigVos(memberDeviceConfigVos);
        result.setUserPoolConfigs(userPoolConfigVos);
        result.setSysLinkVos(sysLinkVos);
        return result;
    }

    /**
     * 先清空数据库，再插入
     *
     * @param vo
     * @return
     */
    @Override
    @Transactional
    public SiteConfigurationVo updateConfig(SiteConfigurationVo vo) {
        SiteConfigurationDO siteConfigurationDO = siteConfigurationMapper.selectById(vo.getId());
        siteConfigurationMapper.deleteById(siteConfigurationDO.getId());
        userPoolConfigService.deleteBySiteCode(siteConfigurationDO.getSiteCode());
        memBerDeviceConfigService.deleteBySiteCode(siteConfigurationDO.getSiteCode());
        sysLinkService.deleteBySiteCode(siteConfigurationDO.getSiteCode());
        this.saveConfig(vo);
        return vo;
    }


}
